package org.tbjd.client.dndControllers.taskList;

import java.util.HashMap;
import java.util.Map;

import org.tbjd.client.constants.NotificationsConstants;
import org.tbjd.client.customWidgets.taskList.TreeGridItemHandle;
import org.tbjd.client.exceptions.NoUpperDecisionmakerFoundException;
import org.tbjd.client.exceptions.NoUpperMediatorFoundException;
import org.tbjd.client.exceptions.TBJDException;
import org.tbjd.client.interfaces.Decisionmaker;
import org.tbjd.client.utils.FlexTableUtil;

import com.allen_sauer.gwt.dnd.client.DragContext;
import com.allen_sauer.gwt.dnd.client.drop.AbstractPositioningDropController;
import com.allen_sauer.gwt.dnd.client.util.CoordinateLocation;
import com.allen_sauer.gwt.dnd.client.util.DOMUtil;
import com.allen_sauer.gwt.dnd.client.util.Location;
import com.allen_sauer.gwt.dnd.client.util.LocationWidgetComparator;
import com.allen_sauer.gwt.dnd.client.util.WidgetLocation;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.IndexedPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.Widget;

public class FlexTableRowDropController extends AbstractPositioningDropController implements Decisionmaker {

	private static final String CSS_DEMO_TABLE_POSITIONER = "demo-table-positioner";

	private FlexTable flexTable;

	private Map<Integer, Object> map = null;

	private Widget draggable = null;

	private IndexedPanel flexTableRowsAsIndexPanel = new IndexedPanel() {

		public Widget getWidget(int index) {
			return flexTable.getWidget(index, 1);
		}

		public int getWidgetCount() {
			return flexTable.getRowCount();
		}

		public int getWidgetIndex(Widget child) {
			throw new UnsupportedOperationException();
		}

		public boolean remove(int index) {
			throw new UnsupportedOperationException();
		}
	};

	private Widget positioner = null;

	private int targetRow;

	public FlexTableRowDropController(FlexTable flexTable) {
		super(flexTable);
		this.flexTable = flexTable;
	}

	public void onDrop(DragContext context) {
		this.draggable = context.draggable;
		
		FlexTableRowDragController trDragController = (FlexTableRowDragController) context.dragController;
		
		TreeGridItemHandle originHandle = (TreeGridItemHandle) this.flexTable.getWidget(trDragController.getDragRow(), 1);
		TreeGridItemHandle targetHandle = (TreeGridItemHandle) this.flexTable.getWidget(targetRow, 1);
		
		FlexTableUtil.moveRow(trDragController.getDraggableTable(), flexTable, trDragController.getDragRow(), targetRow + 1);
		
		super.onDrop(context);

		map = new HashMap<Integer, Object>();

		//map.put(NotificationsConstants.TASKMANAGER_ACTION_treeGridItem_moved, context.draggable);
		//map.put(NotificationsConstants.TREEGRIDITEM_MOVED_ORIGIN_POSITION, trDragController.getDragRow() - 1);
		//map.put(NotificationsConstants.TREEGRIDITEM_MOVED_TARGET_POSITION, targetRow - 1);
		map.put(NotificationsConstants.TASKMANAGER_ACTION_treeGridItemMoved_origin, originHandle.getTask());
		map.put(NotificationsConstants.TASKMANAGER_ACTION_treeGridItemMoved_target, targetHandle.getTask());
		
		try {
			delegate(map);
		} catch (NoUpperDecisionmakerFoundException e) {
			e.printStackTrace();
		} catch (NoUpperMediatorFoundException e) {
			e.printStackTrace();
		}
	}

	public void onEnter(DragContext context) {
		super.onEnter(context);
		positioner = newPositioner(context);
	}

	public void onLeave(DragContext context) {
		positioner.removeFromParent();
		positioner = null;
		super.onLeave(context);
	}

	public void onMove(DragContext context) {

		super.onMove(context);
		targetRow = DOMUtil.findIntersect(flexTableRowsAsIndexPanel, new CoordinateLocation(context.mouseX, context.mouseY),
				LocationWidgetComparator.BOTTOM_HALF_COMPARATOR) - 1;

		Widget w = flexTable.getWidget(targetRow == -1 ? 0 : targetRow, 1);
		Location widgetLocation = new WidgetLocation(w, context.boundaryPanel);
		Location tableLocation = new WidgetLocation(flexTable, context.boundaryPanel);
		context.boundaryPanel.add(positioner, tableLocation.getLeft(), widgetLocation.getTop() + (targetRow == -1 ? 0 : w.getOffsetHeight()));
	}

	Widget newPositioner(DragContext context) {
		Widget p = new SimplePanel();
		p.addStyleName(CSS_DEMO_TABLE_POSITIONER);
		p.setPixelSize(flexTable.getOffsetWidth(), 1);
		return p;
	}

	public void decide(Object action) {
	}

	public void delegate(Object action) throws NoUpperDecisionmakerFoundException, NoUpperMediatorFoundException {

		Widget parent = this.draggable.getParent();

		while (parent != null && parent instanceof Decisionmaker == false) {
			parent = ((Widget) parent).getParent();
		}
		if (parent != null) {
			try {
				((Decisionmaker) parent).decide(action);
			} catch (TBJDException e) {
				e.printStackTrace();
			}
		} else {
			throw new NoUpperDecisionmakerFoundException();
		}
	}

	public void handle(Object action) {

	}

	public int getDropRow() {
		return targetRow;
	}
}
